#———————— 第八章 函数
# 在本章中，你将要学习编写函数（function）
# 函数是带名字的代码块，用于完成具体的工作
# 要执行函数定义的特定任务，可调用（call）该函数

# 你还将学习各种向函数传递信息的方式，学习编写主要任务是显示信息的汉纳树，以及用于处理数据并返回一个或一组值的函数

# 最后，你将学习如何将函数存储在称为模块（module）的独立文件中，让主程序文件更加整洁

# 8.1 定义函数 —————— 关键字 def

# def greet_uesr():
#     """显示简单的问候语"""  # 文档字符串的注释
#     print("Hello!")
# greet_uesr()

# 这个示例演示了最简单的函数结构。
# 第一行代码使用关键字 def 来告诉Python，你要定义一个函数。
# 这是函数定义，向Python 指出了函数名，还可以在括号内指出函数为完成任务需要什么样的信息
# 函数名为 greet_user()，，它不需要任何信息就能完成工作，因此括号内是空的

# 紧跟在def greet_user()：后面的多有缩进行构成了函数体
# 第二行的文本是 文档字符出的注释，描述了函数是做什么的
# Python 在为程序中的函数生成文档时，会查找紧跟在函数定义后的字符串。这些字符串通常前后分别用三个双引号引起，能够包含多行

# 要使用这个函数，必须调用它

# 8.1.1 像函数传递信息

# 只需稍作修改，就可以让函数 greet_user() 在问候用户时以其名字作为抬头。为此，可在定义 def greet_user() 的括号内添加 username

def greet_user(username):
    """显示简单的问候语"""
    print(f"Hello, {username.title()}!")
# 调用该函数
greet_user('jesse')

# 8.1.2 实参和形参

# 8.2 传递实参

# 函数的定义中可能包含多个形参，因此函数调用中也可能包含多个实参。
# 向函数传递实参的方式有很多：既可以使用 位置实参（这要求实参的顺序与形参的顺序相同）
#                        也可以使用 关键字实参（其中每个实参都由变量名和值组成）
#                        还可以使用列表和字典

# 8.2.1 位置实参 —————————— 位置实参的顺序很重要

# 在调用函数时，Python必须将函数调用中的每个实参关联到函数定义中的一个形参。
# 最简单的方式时基于实参的顺序进行关联。
# 以这种方式关联的实参称为 位置实参

def describe_pet(animal_type, pet_name):
    """显示宠物信息"""
    print(f"\nI have a {animal_type}.")
    print(f"\nMy {animal_type}'s name is {pet_name.title()}")

describe_pet('hamster', 'harry')

# 8.2.2 关键字实参 ———————— 名值对
# 关键字实参是传递给函数的名值对。
# 这样会直接在实参中将名称和值关联起来。
# 关键字实参不仅能让你无需考虑函数调用中的实参顺序，而且清楚的指出了函数调用中各个值的用途

describe_pet(animal_type='hamster', pet_name='harry')

# 注意：在使用关键字实参时，无比准确地指定函数定义中的形参名

# 8.2.3 默认值 ———— 需要将未设置默认值的形参放在开头

# 在编写函数时，可以给每个形参指定默认值。
# 如果在调用函数中给形参提供了实参，Python将使用指定的实参值；
# 否则将使用形参的默认值。

# 因此，给形参指定默认值后，可在函数调用中省略相应的实参。
# 使用默认值不仅能简化函数调用，还能清楚的指出函数的典型用法

def describe_pet(pet_name, animal_type= 'dog'):
    # 发现描述的大多是小狗，就可将 animal_type的默认值设为 'dog'
    """显示宠物的信息"""
    print(f"\nI have a {animal_type}.")
    print(f"\nMy {animal_type}'s name is {pet_name.title()}")

describe_pet(pet_name='willie')
describe_pet(pet_name='willie', animal_type='cat')#提供了实参时，会忽略默认值

# 请注意，在这个函数的定义中，修改了形参的排列顺序
# 由于给animal_type 指定了默认值，无需通过实参来指定动物的类型，因此函数调用只包含一个实参
# 然而，Python依然将这个实参视为位置实参，如果函数调用只包含宠物的名字，这个实参将被关联导函数定义的第一个形参
# 这就是需要将pet_name 放在形参列表开头的原因

# 8.2.4 等效的函数调用

# 鉴于可以缓和使用位置实参，关键字实参和默认值，通常还有多种等效的函数调用方式：

# 小狗，willie
describe_pet('willie')
describe_pet(pet_name='willie')

# 仓鼠 Harry
describe_pet('harry', 'hamster')
describe_pet(pet_name='harry', animal_type='hamster')
describe_pet(animal_type='hamster', pet_name='harry')

# 8.2.5 避免实参错误
# 等你开始使用函数后，也许会遇到实参不匹配的错误。
# 当你提供的实参多于或少于函数完成所需的实参数量时，将出现实参不匹配错误

# 报错 


















































































